package com.yuju.account.service.impl;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.yuju.account.dao.IUnitAccountDao;
import com.yuju.account.dao.entity.UnitAccount;
import com.yuju.account.enums.AccountStatusEnum;
import com.yuju.account.enums.AccountTypeEnum;
import com.yuju.account.enums.BusinessTypeDetailEnum;
import com.yuju.account.enums.BusinessTypeEnum;
import com.yuju.account.enums.UnitAccountBookReturnCodeEnum;
import com.yuju.account.enums.UnitAccountReturnCodeEnum;
import com.yuju.account.enums.UnitAccountSettleEnum;
import com.yuju.account.model.UnitAccountBookModel;
import com.yuju.account.model.UnitAccountModel;
import com.yuju.account.service.IShiftService;
import com.yuju.account.service.IUnitAccountBookService;
import com.yuju.account.service.IUnitAccountService;
import com.yuju.common.PageModel;
import com.yuju.common.core.dao.IBaseDao;
import com.yuju.common.core.service.AbstractBaseService;
import com.yuju.enums.ReturnCodeEnum;
import com.yuju.enums.StatusEnum;
import com.yuju.exception.BusinessException;
import com.yuju.group.enums.AgentCustomReturnCodeEnum;
import com.yuju.group.enums.ProtocolCustomReturnCodeEnum;
import com.yuju.group.service.ICodeGenService;
import com.yuju.hotel.enums.CustomersEnum;
import com.yuju.util.DateUtil;
import com.yuju.util.ExcelExp;
import com.yuju.util.Utils;

/**
 * 类名：UnitAccountServiceImpl <br />
 *
 * 功能：
 *
 * @author : jiaokn <br />
 * @Date : 2017年11月27日 上午10:28:08 <br />
 * @version : 1.1 <br />
 */
@Service
public class UnitAccountServiceImpl extends AbstractBaseService<UnitAccountModel, UnitAccount, String>
		implements IUnitAccountService {

	@Autowired
	private IUnitAccountDao unitAccountDao;
	
	@Autowired
	private ICodeGenService codeGenService;
	
	@Autowired
	private IUnitAccountBookService unitAccountBookService;
	
	@Autowired
	private IShiftService shiftService;

	@Override
	public IBaseDao<UnitAccountModel, UnitAccount, String> getDao() {
		// TODO Auto-generated method stub
		return unitAccountDao;
	}

	/**
	 * 功能: 重写新增单位账务方法<br/>
	 * 
	 * 重写：jiaokn <br/>
	 * 
	 * @Date ：2017年11月27日 上午10:30:43<br/>
	 * 
	 * @param unitAccountModel
	 * @return <br/>
	 * @see com.yuju.common.core.service.AbstractBaseService#save(java.lang.Object)
	 */
	@Override
	public int save(UnitAccountModel unitAccountModel) {
		unitAccountModel.setClassNo(shiftService.getCurrentClassId(unitAccountModel.getHotelId()));
		unitAccountModel.setId(Utils.getUUID());
		unitAccountModel.setGmtCreate(new Date());
		unitAccountModel.setGmtModified(new Date());
		return super.save(unitAccountModel);
	}

	/**
	 * 功能:新增单位账务 <br/>
	 * 
	 * 1.根据账务类型判断单位或中介的挂账余额应该加还是减
	 * 2.根据客户类型和客户ID更新对应协议单位或中介的挂账余额
	 * 3.新增单位账务
	 * 
	 * 重写：jiaokn <br/>
	 * 
	 * @Date ：2017年12月7日 下午3:25:34<br/>
	 * 
	 * @param unitAccountModel
	 * @return <br/>
	 * @see com.yuju.account.service.IUnitAccountService#insertUnitAccount(com.yuju.account.model.UnitAccountModel)
	 */
	@Override
	public int saveUnitAccount(UnitAccountModel unitAccountModel) {
		// 设置编码
		unitAccountModel
				.setAccountCode(codeGenService.generate(unitAccountModel.getGroupId(), unitAccountModel.getHotelId(),
						unitAccountModel.getHotelCode(), BusinessTypeEnum.getType(unitAccountModel.getBusinessType())));

		BigDecimal money = new BigDecimal(0);
		if (unitAccountModel.getAccountType() == AccountTypeEnum.ACCOUNT_TYPE_YS.getValue()) {
			// 应收 挂账余额应减
			money = unitAccountModel.getMoney().multiply(new BigDecimal(-1));
		} else if (unitAccountModel.getAccountType() == AccountTypeEnum.ACCOUNT_TYPE_SS.getValue()) {
			if (unitAccountModel.getBusinessTypeDetail() == BusinessTypeDetailEnum.BUSINESS_TYPE_DETAIL_XJTK.getValue()
					|| unitAccountModel.getBusinessTypeDetail() == BusinessTypeDetailEnum.BUSINESS_TYPE_DETAIL_ZZTK
							.getValue()
					|| unitAccountModel.getBusinessTypeDetail() == BusinessTypeDetailEnum.BUSINESS_TYPE_DETAIL_SKTK
							.getValue()
					|| unitAccountModel.getBusinessTypeDetail() == BusinessTypeDetailEnum.BUSINESS_TYPE_DETAIL_WXTK
							.getValue()
					|| unitAccountModel.getBusinessTypeDetail() == BusinessTypeDetailEnum.BUSINESS_TYPE_DETAIL_ZFBTK
							.getValue()) {
				money = unitAccountModel.getMoney().multiply(new BigDecimal(-1));
			}else{
				money = unitAccountModel.getMoney();
			}
		} else {
			return 0;
		}
		// 封装参数
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("id", unitAccountModel.getCustomId());
		map.put("money", money);
		map.put("gmtModified", new Date());

		if (unitAccountModel.getCustomType() == CustomersEnum.CUSTOMERS_XYDW.getValue()) {
			// 根据ID更新协议单位的挂账余额
			if (unitAccountDao.updateProtocolBalance(map) < 1) {
				throw new BusinessException(ProtocolCustomReturnCodeEnum.PROTOCOLCUSTOM_UPDATE_FAILURE.getCode(),
						ProtocolCustomReturnCodeEnum.PROTOCOLCUSTOM_UPDATE_FAILURE.getDesc());
			}
		} else if (unitAccountModel.getCustomType() == CustomersEnum.CUSTOMERS_ZJ.getValue()) {
			// 根据ID更新中介的挂账余额
			if (unitAccountDao.updateAgentBalance(map) < 1) {
				throw new BusinessException(AgentCustomReturnCodeEnum.AGENTCUSTOM_UPDATE_FAILURE.getCode(),
						AgentCustomReturnCodeEnum.AGENTCUSTOM_UPDATE_FAILURE.getDesc());
			}
		} else {
			throw new BusinessException(UnitAccountReturnCodeEnum.UNITACCOUNT_CUSTOMER_FAILURE.getCode(),
					UnitAccountReturnCodeEnum.UNITACCOUNT_CUSTOMER_FAILURE.getDesc());
		}
		// 新增单位账务
		return this.save(unitAccountModel);
	}

	/**
	 * 功能:单位账务结账功能 <br/>
	 * 
	 * 1.根据accountBookId判断是否是按帐套结算 如果是，更新帐套的结算状态；如果不是，新增一个帐套并得到此帐套的ID
	 * 2.更新原账务的帐套id和结账状态
	 * 3.循环新增单位账务
	 * 
	 * 重写：jiaokn <br/>
	 * 
	 * @Date ：2017年12月8日 下午6:18:51<br/>
	 * 
	 * @param param
	 * @return <br/>
	 * @see com.yuju.account.service.IUnitAccountService#settle(java.util.Map)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public String saveSettle(Map<String, Object> param) {
		// 获得参数
		String accountBookId = (String) param.get("accountBookId");
		String customId = (String) param.get("customId");
		Byte customType = (Byte) param.get("customType");
		String hotelId = (String) param.get("hotelId");
		String groupId = (String) param.get("groupId");
		String hotelCode = (String) param.get("hotelCode");
		String empId = (String) param.get("empId");

		ArrayList<String> unitAccountIdList = (ArrayList<String>) param.get("unitAccountIdList");
		ArrayList<UnitAccountModel> unitAccountModelList = (ArrayList<UnitAccountModel>) param
				.get("unitAccountModelList");

		// 获得帐套ID
		if (Utils.isNull(accountBookId)) {
			UnitAccountBookModel unitAccountBookModel = new UnitAccountBookModel();
			unitAccountBookModel.setCustomId(customId);
			unitAccountBookModel.setCustomType(customType);
			unitAccountBookModel.setIsSettle(UnitAccountSettleEnum.TRUE.getValue());
			unitAccountBookModel.setSettleTime(new Date());
			unitAccountBookModel.setCreateUserId(empId);
			unitAccountBookModel.setUpdateUserId(empId);
			SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
			unitAccountBookModel.setName("系统生成"+sdf.format(new Date()));
			unitAccountBookModel.setHotelId(hotelId);
			unitAccountBookModel.setGroupId(groupId);
			accountBookId = unitAccountBookService.saveAndGetId(unitAccountBookModel);
			if(Utils.isNull(accountBookId)){
				throw new BusinessException(UnitAccountBookReturnCodeEnum.UNITACCOUNTBOOK_SAVE_FAILURE.getCode(),
						UnitAccountBookReturnCodeEnum.UNITACCOUNTBOOK_SAVE_FAILURE.getDesc());
			}
		}else{
			UnitAccountBookModel unitAccountBookModel = new UnitAccountBookModel();
			unitAccountBookModel.setId(accountBookId);
			unitAccountBookModel.setIsSettle(UnitAccountSettleEnum.TRUE.getValue());
			unitAccountBookModel.setSettleTime(new Date());
			unitAccountBookModel.setUpdateUserId(empId);
			unitAccountBookModel.setGmtModified(new Date());
			if(unitAccountBookService.updateSelective(unitAccountBookModel)<1){
				throw new BusinessException(UnitAccountBookReturnCodeEnum.UNITACCOUNTBOOK_UPDATE_FAILURE.getCode(),
						UnitAccountBookReturnCodeEnum.UNITACCOUNTBOOK_UPDATE_FAILURE.getDesc());
			}
		}
		// 更新结账账务
		for (String unitAccountId : unitAccountIdList) {
			UnitAccountModel unitAccountModel = new UnitAccountModel();
			unitAccountModel.setId(unitAccountId);
			unitAccountModel.setAccountBookId(accountBookId);
			unitAccountModel.setIsSettle(UnitAccountSettleEnum.TRUE.getValue());
			unitAccountModel.setSettleTime(new Date());
			unitAccountModel.setUpdateUserId(empId);
			unitAccountModel.setGmtModified(new Date());
			if(this.updateSelective(unitAccountModel)<1){
				throw new BusinessException(UnitAccountReturnCodeEnum.UNITACCOUNT_UPDATE_FAILURE.getCode(),
						UnitAccountReturnCodeEnum.UNITACCOUNT_UPDATE_FAILURE.getDesc());
			}
			
		}
		// 添加单位账务
		for (UnitAccountModel unitAccountModel : unitAccountModelList) {
			//id为空 则是新增账务 进行新增操作
			if(Utils.isNull(unitAccountModel.getId())){
				unitAccountModel.setAccountType(AccountTypeEnum.ACCOUNT_TYPE_SS.getValue());
				unitAccountModel.setBusinessTypeName(BusinessTypeEnum.getName(unitAccountModel.getBusinessType()));
				unitAccountModel.setBusinessTypeDetailName(
						BusinessTypeDetailEnum.getName(unitAccountModel.getBusinessTypeDetail()));
				if(unitAccountModel.getAccountStatus() == AccountStatusEnum.STATUS_OK.getValue()){
					unitAccountModel.setAccountStatusName(AccountStatusEnum.STATUS_OK.getName());
					unitAccountModel.setCreateUserId(empId);
				}else{
					unitAccountModel.setAccountStatusName(AccountStatusEnum.STATUS_DEL.getName());
					unitAccountModel.setUpdateUserId(empId);
				}
				unitAccountModel.setCustomId(customId);
				unitAccountModel.setCustomType(customType);
				unitAccountModel.setAccountBookId(accountBookId);
				unitAccountModel.setHotelId(hotelId);
				unitAccountModel.setGroupId(groupId);
				unitAccountModel.setHotelCode(hotelCode);
	
				if (this.saveUnitAccount(unitAccountModel) < 1) {
					throw new BusinessException(UnitAccountReturnCodeEnum.UNITACCOUNT_SAVE_FAILURE.getCode(),
							UnitAccountReturnCodeEnum.UNITACCOUNT_SAVE_FAILURE.getDesc());
				}
			}else{//id 不为空 则是原有账务 如果状态是取消 则进行冲调操作 如果是正常 不进行任何操作
				if(unitAccountModel.getAccountStatus() == AccountStatusEnum.STATUS_CANCEL.getValue()){
					unitAccountModel.setGmtModified(new Date());
					unitAccountModel.setAccountStatusName(AccountStatusEnum.STATUS_CANCEL.getName());
					unitAccountModel.setUpdateUserId(empId);
					if(this.updateSelective(unitAccountModel)<1){
						throw new BusinessException(UnitAccountReturnCodeEnum.UNITACCOUNT_UPDATE_FAILURE.getCode(),
								UnitAccountReturnCodeEnum.UNITACCOUNT_UPDATE_FAILURE.getDesc());
					}
				}
			}
		}
		return accountBookId;
	}

	/**
	 * 功能:新增单位账务(不结算) <br/>
	 * 
	 * 循环增加账务
	 * 
	 * 重写：jiaokn <br/>
	 * 
	 * @Date ：2017年12月14日 下午4:54:50<br/>
	 * 
	 * @param param
	 * @return <br/>
	 * @see com.yuju.account.service.IUnitAccountService#saveUnitAccount(java.util.Map)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public String saveUnitAccountList(Map<String, Object> param) {
		// 获得参数
		String accountBookId = (String) param.get("accountBookId");
		String customId = (String) param.get("customId");
		Byte customType = (Byte) param.get("customType");
		String hotelId = (String) param.get("hotelId");
		String groupId = (String) param.get("groupId");
		String hotelCode = (String) param.get("hotelCode");
		String empId = (String) param.get("empId");
		ArrayList<UnitAccountModel> unitAccountModelList = (ArrayList<UnitAccountModel>) param
				.get("unitAccountModelList");
		
		for (UnitAccountModel unitAccountModel : unitAccountModelList) {
			//如果id不为空 状态为取消 执行冲调操作，如果状态正常 不进行任何操作
			if(Utils.isNotNull(unitAccountModel.getId())){
				if(unitAccountModel.getAccountStatus() == AccountStatusEnum.STATUS_CANCEL.getValue()){
					unitAccountModel.setGmtModified(new Date());
					unitAccountModel.setAccountStatusName(AccountStatusEnum.STATUS_CANCEL.getName());
					unitAccountModel.setUpdateUserId(empId);
					if(this.updateSelective(unitAccountModel)<1){
						throw new BusinessException(UnitAccountReturnCodeEnum.UNITACCOUNT_UPDATE_FAILURE.getCode(),
								UnitAccountReturnCodeEnum.UNITACCOUNT_UPDATE_FAILURE.getDesc());
					}
				}
			}else{//id为空 新增账务
				unitAccountModel.setAccountType(AccountTypeEnum.ACCOUNT_TYPE_SS.getValue());
				unitAccountModel.setBusinessTypeName(BusinessTypeEnum.getName(unitAccountModel.getBusinessType()));
				unitAccountModel.setBusinessTypeDetailName(
						BusinessTypeDetailEnum.getName(unitAccountModel.getBusinessTypeDetail()));
				if(unitAccountModel.getAccountStatus() == AccountStatusEnum.STATUS_OK.getValue()){
					unitAccountModel.setAccountStatusName(AccountStatusEnum.STATUS_OK.getName());
					unitAccountModel.setCreateUserId(empId);
				}else{
					unitAccountModel.setAccountStatusName(AccountStatusEnum.STATUS_DEL.getName());
					unitAccountModel.setUpdateUserId(empId);
				}
				unitAccountModel.setCustomId(customId);
				unitAccountModel.setCustomType(customType);
				unitAccountModel.setAccountBookId(accountBookId);
				unitAccountModel.setHotelId(hotelId);
				unitAccountModel.setGroupId(groupId);
				unitAccountModel.setHotelCode(hotelCode);
	
				if (this.saveUnitAccount(unitAccountModel) < 1) {
					throw new BusinessException(UnitAccountReturnCodeEnum.UNITACCOUNT_SAVE_FAILURE.getCode(),
							UnitAccountReturnCodeEnum.UNITACCOUNT_SAVE_FAILURE.getDesc());
				}
			}
		}
		return accountBookId;
	}

	/**
	 * 功能:单位账务列表查询 <br/>
	 * 
	 * 重写：jiaokn <br/>
	 * 
	 * @Date ：2017年12月15日 下午2:51:28<br/>
	 * 
	 * @param unitAccountModel
	 * @param currentPage
	 * @param rows
	 * @return <br/>
	 * @see com.yuju.account.service.IUnitAccountService#listUnitAccount(com.yuju.account.model.UnitAccountModel, java.lang.Integer, java.lang.Integer)
	 */
	@Override
	public PageModel pageListUnitAccount(UnitAccountModel unitAccountModel, Integer currentPage, Integer rows) {
		return unitAccountDao.pageListUnitAccount(unitAccountModel, currentPage, rows);
	}

	/**
	 * 功能:单位账务处理列表查询 <br/>
	 * 
	 * 重写：jiaokn <br/>
	 * 
	 * @Date ：2017年12月16日 上午11:26:55<br/>
	 * 
	 * @param unitAccountModel
	 * @param currentPage
	 * @param rows
	 * @return <br/>
	 * @see com.yuju.account.service.IUnitAccountService#listUnitAccountAndSum(com.yuju.account.model.UnitAccountModel, java.lang.Integer, java.lang.Integer)
	 */
	@Override
	public PageModel listUnitAccountAndSum(UnitAccountModel unitAccountModel, Integer currentPage, Integer rows) {
		return unitAccountDao.listUnitAccountAndSum(unitAccountModel, currentPage, rows);
	}

	/**
	 * 功能: 单位账务列表查询（不分页）<br/>
	 * 
	 * 重写：jiaokn <br/>
	 * 
	 * @Date ：2017年12月16日 下午4:22:44<br/>
	 * 
	 * @param unitAccountModel
	 * @return <br/>
	 * @see com.yuju.account.service.IUnitAccountService#listUnitAccount(com.yuju.account.model.UnitAccountModel)
	 */
	@Override
	public List<UnitAccount> listUnitAccount(UnitAccountModel unitAccountModel) {
		return unitAccountDao.listUnitAccount(unitAccountModel);
	}

	/**
	 * 功能:单位实收账务查找 <br/>
	 * 
	 * 重写：jiaokn <br/>
	 * 
	 * @Date ：2017年12月19日 下午4:57:10<br/>
	 * 
	 * @param unitAccountModel
	 * @param currentPage
	 * @param rows
	 * @return <br/>
	 * @see com.yuju.account.service.IUnitAccountService#listUnitAccountSS(com.yuju.account.model.UnitAccountModel, java.lang.Integer, java.lang.Integer)
	 */
	@Override
	public PageModel listUnitAccountSS(UnitAccountModel unitAccountModel,Integer currentPage, Integer rows) {
		return unitAccountDao.listUnitAccountSS(unitAccountModel, currentPage, rows);
	}

	/**
	 * 功能:获得单位预收款余额 <br/>
	 * 
	 * 重写：jiaokn <br/>
	 * 
	 * @Date ：2017年12月23日 下午3:57:26<br/>
	 * 
	 * @param unitAccountModel
	 * @return <br/>
	 * @see com.yuju.account.service.IUnitAccountService#getYSK(com.yuju.account.model.UnitAccountModel)
	 */
	@Override
	public Map<Object, Object> getYSK(UnitAccountModel unitAccountModel) {
		return unitAccountDao.getYSK(unitAccountModel);
	}


	@Override
	public List<UnitAccountModel> listUnitAccountSSNoPage(UnitAccountModel unitAccountModel) {
		return unitAccountDao.listUnitAccountSSNoPage(unitAccountModel);
	}

	@Override
	public byte[] expBusinessDailySubRpt(UnitAccountModel unitAccountModel) throws IOException {
		ExcelExp e = new ExcelExp();
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		e.createRow(0);
		e.setCell(0, "单位/中介");
		e.setCell(1, "业务类型");
		e.setCell(2, "金额");
		e.setCell(3, "消费时间");
		e.setCell(4, "班次号");
		e.setColumnWidth(0, 5000);
		e.setColumnWidth(1, 3000);
		e.setColumnWidth(2, 3000);
		e.setColumnWidth(3, 5000);
		e.setColumnWidth(4, 6000);
		
		BigDecimal money = unitAccountModel.getMoney();
		unitAccountModel.setMoney(null);
		List<UnitAccountModel> list = this.listUnitAccountSSNoPage(unitAccountModel);
		if(Utils.isNull(list)){
			throw new BusinessException(ReturnCodeEnum.NO_DATA.getCode(), ReturnCodeEnum.NO_DATA.getDesc());
		}
		for (int i = 0; i < list.size(); i++) {
			e.createRow(i+1);
			e.setCell(0, list.get(i).getCustomName());
			e.setCell(2, list.get(i).getBusinessDetail());
			e.setCell(3, list.get(i).getMoney().toString());
			e.setCell(4, DateUtil.format(list.get(i).getGmtCreate()));
			e.setCell(5, list.get(i).getClassCode());
		}
		e.createRow(list.size()+1);
		e.setCell(0, "合计");
		e.setCell(2, money.toString());
		e.getWorkbook().write(os);
		os.flush();
		return os.toByteArray();
	}

	@Override
	public BigDecimal listUnitAccountSum(UnitAccountModel unitAccountModel) {
		return unitAccountDao.listUnitAccountSum(unitAccountModel);
	}

	@Override
	public byte[] expUnitAccountExcel(UnitAccountModel unitAccountModel) throws IOException {
		ExcelExp e = new ExcelExp();
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		e.createRow(0);
		e.setCell(0, "姓名");
		e.setCell(1, "房号");
		e.setCell(2, "房型");
		e.setCell(3, "挂账时间");
		e.setCell(4, "挂账金额");
		e.setCell(5, "挂账单位/中介");
		e.setCell(6, "操作人");
		e.setCell(7, "结账状态");
		e.setColumnWidth(0, 5000);
		e.setColumnWidth(1, 5000);
		e.setColumnWidth(2, 5000);
		e.setColumnWidth(3, 5000);
		e.setColumnWidth(4, 5000);
		e.setColumnWidth(5, 5000);
		e.setColumnWidth(6, 5000);
		e.setColumnWidth(7, 5000);
		
		List<UnitAccount> list = this.listUnitAccount(unitAccountModel);
		BigDecimal sum = this.listUnitAccountSum(unitAccountModel);
		if(Utils.isNull(sum) || Utils.isNull(list)){
			throw new BusinessException(ReturnCodeEnum.NO_DATA.getCode(), ReturnCodeEnum.NO_DATA.getDesc());
		}
		for (int i = 0; i < list.size(); i++) {
			e.createRow(i+1);
			e.setCell(0, list.get(i).getGuestName());
			e.setCell(1, list.get(i).getRoomCode());
			e.setCell(2, list.get(i).getRoomTypeName());
			e.setCell(3, DateUtil.format(list.get(i).getGmtCreate()));
			e.setCell(4, list.get(i).getMoney().toString());
			e.setCell(5, list.get(i).getCustomName());
			e.setCell(6, list.get(i).getCreateUserName());
			if(list.get(i).getIsSettle() == StatusEnum.TRUE.getValue()){
				e.setCell(7, "已结");
			}else{
				e.setCell(7, "未结");
			}
		}
		e.createRow(list.size()+1);
		e.setCell(0, "合计");
		e.setCell(4, sum.toString());
		e.getWorkbook().write(os);
		os.flush();
		return os.toByteArray();
	}


}
